package it.uniroma2.mpsr;

import it.uniroma2.mpsr.algorithms.FP;
import it.uniroma2.mpsr.algorithms.MVA;
import it.uniroma2.mpsr.config.Configuration;
import it.uniroma2.mpsr.resources.Centre;
import it.uniroma2.mpsr.resources.FPResults;
import it.uniroma2.mpsr.resources.MVAResults;
import it.uniroma2.mpsr.resources.State;

import java.io.File;
import java.util.ArrayList;

public class FPMVASolver {

	public static void main(String[] args) {
		Configuration.getInstance().configure("conf"+File.separator+"rete1.xml");
		String[][] routingAsString1 = Configuration.getInstance().getMatrix();
		double[][] routing1 = new double[routingAsString1.length][routingAsString1.length];

		for (int i = 0; i < routingAsString1.length; i++) {
			for (int j = 0; j < routingAsString1[i].length; j++) {
				routing1[i][j] = Double.parseDouble(routingAsString1[i][j]);
			}
		}

		Centre[] centres1 = Configuration.getInstance().getCentres();
		int N1 = Configuration.getInstance().getN();

		FPResults fpr1 = FP.solve(routing1, centres1, N1);
		fpr1.print();
		State[] states1 = fpr1.getStates();

		double[] pSats = new double[N1 + 2];
		
		ArrayList<Integer> al = new ArrayList<Integer>();
		for(int i = 0; i < centres1.length; i++) {
			if(centres1[i].getKind().equals("SPC")) {
				al.add(i);
			}
		}

		for(int S = 0; S < N1 + 2; S++) {
			for(int i = 0; i < states1.length; i++) {
				int sum = 0;
				for(int j = 0; j < al.size(); j++) {
					int jobs = states1[i].getElement(al.get(j));
					sum += jobs;
				}
				if(sum >= S) {
					pSats[S] += states1[i].getStatProb();
				}
			}
			System.out.println(S + ": pSat = " + pSats[S]);
		}

		Configuration.getInstance().configure("conf"+File.separator+"rete2xy.xml");
		String[][] routingAsString2 = Configuration.getInstance().getMatrix();
		double[][] routing2 = new double[routingAsString2.length][routingAsString2.length];
		Centre[] centres2 = Configuration.getInstance().getCentres();
		int N2 = Configuration.getInstance().getN();
		
		int bestS1 = -1, bestS2 = -1;
		double minRespTimeC1 = -1;
		
		for(int r = 0; r < pSats.length; r++) {
			double p_c1_c1_rj = pSats[r];
			if (p_c1_c1_rj > 0.01 && p_c1_c1_rj < 0.25) {

				for(int s = 0; s < pSats.length; s++) {
					double p_c2_c2_rj = pSats[s];
					if (p_c2_c2_rj > 0.01 && p_c2_c2_rj < 0.25 && p_c2_c2_rj < p_c1_c1_rj) {

						for (int i = 0; i < routingAsString2.length; i++) {
							for (int j = 0; j < routingAsString2[i].length; j++) {
								String[] operandsAsString = routingAsString2[i][j].split("-");
								double[] operands = new double[operandsAsString.length];
								for(int h = 0; h < operandsAsString.length; h++) {
									operandsAsString[h] = operandsAsString[h].replaceAll("x", p_c1_c1_rj+"");
									operandsAsString[h] = operandsAsString[h].replaceAll("y", p_c2_c2_rj+"");
									operands[h] = Double.parseDouble(operandsAsString[h]);
								}
								routing2[i][j] = operands[0];
								for(int h = 1; h < operands.length; h++)
									routing2[i][j] -= operands[h];
							}
						}

						MVAResults mvar = MVA.solve(routing2, centres2, N2);
						System.out.print("\n\n\n(S1 = " + r + ", S2 = " + s + ") ");
						mvar.print();
						if(minRespTimeC1 < 0 || minRespTimeC1 > mvar.getResponseTime()[0]) {
							minRespTimeC1 = mvar.getResponseTime()[0];
							bestS1 = r;
							bestS2 = s;
						}
					}
				}
			}
		}
		
		System.out.println("\n\n\nLe soglie che minimizzano il tempo medio di risposta per Client1 sono: S1 = " + bestS1 + ", S2 = " + bestS2);
		System.out.println("\tE[tr_client1] = " + minRespTimeC1 + "\n\n");
	}
}
